package org.example.pinda.util.date;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Date;

/**
 * 日期工具类
 * <p>
 * 格式化日期的默认格式为 {@link DateUtils#DEFAULT_DATE_TIME_FORMAT}: yyyy-MM-dd HH:mm:ss
 *
 * @author ryan fawcett
 */
public class DateUtils {
    public static final String DEFAULT_YEAR_FORMAT = "yyyy";
    public static final String DEFAULT_MONTH_FORMAT = "yyyy-MM";
    public static final String DEFAULT_MONTH_FORMAT_SLASH = "yyyy/MM";
    public static final String DEFAULT_MONTH_FORMAT_CN = "yyyy年MM月";
    public static final String DEFAULT_WEEK_FORMAT = "yyyy-ww";
    public static final String DEFAULT_WEEK_FORMAT_CN = "yyyy年ww周";
    public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
    public static final String DEFAULT_DATE_FORMAT_CN = "yyyy年MM月dd日";
    public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
    public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";
    public static final String DAY = "DAY";
    public static final String MONTH = "MONTH";
    public static final String WEEK = "WEEK";

    /**
     * 一个月平均天数
     */
    public static final int MAX_MONTH_DAY = 30;
    /**
     * 三个月平均天数
     */
    public static final int MAX_3_MONTH_DAY = 90;
    /**
     * 一年平均天数
     */
    public static final int MAX_YEAR_DAY = 365;

    // ----------------------------- 格式化日期 ----------------------------------

    /**
     * 指定格式格式化日期.<br/>
     * 如果传入的日期对象为 null，则将其赋值为当前时间;<br/>
     * 如果传入的格式为空或者空字符串，则使用默认的格式进行格式化操作，默认的格式为 yyyy-MM-dd HH:mm:ss
     *
     * @param date   将要格式化的日期对象
     * @param format 格式化的格式
     * @return 格式化后的日期字符串，默认格式为: yyyy-MM-dd HH:mm:ss
     * @see DateUtils#DEFAULT_DATE_TIME_FORMAT
     */
    public static String format(Date date, String format) {
        if (date == null) {
            date = new Date();
        }
        if (format == null || format.length() == 0) {
            format = DEFAULT_DATE_TIME_FORMAT;
        }
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        return sdf.format(date);
    }

    /**
     * 使用默认格式将指定日期转换为日期字符串
     *
     * @param source 转换的日期
     * @return 日期字符串，格式为：yyyy-MM-dd HH:mm:ss
     * @see DateUtils#DEFAULT_DATE_TIME_FORMAT
     */
    public static String format(Date source) {
        return format(source, DEFAULT_DATE_TIME_FORMAT);
    }

    /**
     * 将当前的时间转换为日期字符串
     *
     * @return 日期字符串，格式为: yyyy-MM-dd HH:mm:ss
     * @see DateUtils#DEFAULT_DATE_TIME_FORMAT
     */
    public static String format() {
        return format(null);
    }

    /**
     * 将指定日期对象转换为日期字符串
     *
     * @param source 转换的日期对象
     * @return 日期字符串，格式为：yyyy-MM-dd
     * @see DateUtils#DEFAULT_DATE_FORMAT
     */
    public static String formatDate(Date source) {
        return format(source, DEFAULT_DATE_FORMAT);
    }

    // ----------------------------- 解析日期 ------------------------------------

    /**
     * 将日期字符串以指定格式解析为日期对象.<br/>
     * 如果传入的格式为空或者空字符串，则使用默认格式进行转换.<br/>
     * <p>
     * 注意：这里需要将{@link SimpleDateFormat}的自动计算日期的功能禁止，即如果格式化的日期不合法
     * 就直接抛出异常
     *
     * @param source 日期字符串
     * @param format 解析的格式，默认格式为：yyyy-MM-dd HH:mm:ss
     * @return 日期对象
     */
    public static Date parse(String source, String format) {
        if (format == null || "".equals(format)) {
            format = DEFAULT_DATE_TIME_FORMAT;
        }

        SimpleDateFormat sdf = new SimpleDateFormat(format);
        sdf.setLenient(false); // 禁止自动计算日期功能，如果日期不合法就直接抛出异常

        Date date = null;
        try {
            date = sdf.parse(source);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }

    /**
     * 将日期字符串以默认格式解析为日期对象
     *
     * @param source 日期字符串，格式为：yyyy-MM-dd HH:mm:ss
     * @return 日期对象
     * @see DateUtils#DEFAULT_DATE_TIME_FORMAT
     */
    public static Date parse(String source) {
        return parse(source, DEFAULT_DATE_TIME_FORMAT);
    }

    /**
     * 将日期字符串转换为日期对象
     *
     * @param source 日期字符串
     * @return 日期对象
     * @see DateUtils#DEFAULT_DATE_FORMAT
     */
    public static Date parseDate(String source) {
        return parse(source, DEFAULT_DATE_FORMAT);
    }

    /**
     * 将LocalDateTime转化为Date对象
     */
    public static Date localDateTime2Date(LocalDateTime localDateTime) {
        ZoneId zoneId = ZoneId.systemDefault();
        ZonedDateTime zdt = localDateTime.atZone(zoneId);
        return Date.from(zdt.toInstant());
    }
}
